import { getRootOrg, getOrgsByParentCode, getUserByOrgCode, getUserListByNameFuzzy, selectEmployeeList } from "../services/fourAApi";

const walk = (orgCode, childOrgs, handler) => {
  const orgCodes = [orgCode];
  const orgCodeChilredMap = {
    [orgCode]: childOrgs,
  };
  let currentOrgCode;
  while (orgCodes.length > 0) {
    currentOrgCode = orgCodes.shift();
    const _childOrgs = orgCodeChilredMap[currentOrgCode].map(org => {
      const { children, ...orgInfo } = org;
      const { ORG_CODE } = orgInfo;
      if (children) {
        orgCodes.push(ORG_CODE);
        orgCodeChilredMap[ORG_CODE] = children;
      }
      return orgInfo;
    })
    handler(currentOrgCode, _childOrgs);
  }
}

const initData = {
  cachedCodeOrgsMap: null,
  listSearchData: [],
};

export default {
  namespace: "usertreeSelect",
  state: {
    ...initData,
  },
  effects: {
    *getRootOrg({ payload }, { call }) {
      const { datas = {}, errCode, errMsg } = yield call(getRootOrg, payload);
      // 兼容接口没有返回extentAttributes信息的情况, 此时接口只返回了下一层
      if (Array.isArray(datas)) {
        datas.forEach((item) => {
          if (item.displayName && !item.extentAttributes && !item.extentAttribute) {
            item.extentAttributes = {
              ORG_CODE: item.code,
              ORG_NAME: item.displayName,
            }
          }
        });
      }
      return { errCode, errMsg, datas }
    },
    // 杭州4A会把整个组织树返回，因此做缓存访问下级时直接从缓存中读取
    // 同时兼容旧版只返回下一级组织的接口(没有children字段)
    *getChildren({ payload, isJustLoadOrg }, { call, put, select }) {
      const { orgCode, orgName } = payload;
      let errCode = 0
      let errMsg = '';
      let cachedCodeOrgsMap =
        yield select(({ usertreeSelect }) => usertreeSelect.cachedCodeOrgsMap);

      if (!cachedCodeOrgsMap || !cachedCodeOrgsMap[orgCode]) {
        const { datas: orgData = [], errCode: _c, errMsg: _m } =
          yield call(getOrgsByParentCode, payload);
        errCode = _c;
        errMsg = _m;
        if (errCode === 0) {
          cachedCodeOrgsMap = {
            ...cachedCodeOrgsMap, // may be null
          };
          walk(orgCode, orgData, (pCode, childOrgs) => {
            // 兼容接口没有返回extentAttributes信息的情况, 此时接口只返回了下一层
            // 所以extendAttributes统一用参数的
            if (childOrgs && childOrgs.length > 0) {
              childOrgs.forEach((childOrg) => {
                // 确保是缺少父组织的数据结构
                if (childOrg.displayName && !childOrg.extentAttributes && !childOrg.extentAttribute) {
                  childOrg.extentAttributes = {
                    ORG_CODE: orgCode,
                    ORG_NAME: orgName,
                  }
                }
              });
            }
            cachedCodeOrgsMap[pCode] = childOrgs;
          });
          yield put({
            type: 'set/cachedCodeOrgsMap',
            payload: cachedCodeOrgsMap,
          });
        }
      }
      let childData;
      if (cachedCodeOrgsMap) {
        childData = cachedCodeOrgsMap[orgCode] || [];
      } else {
        childData = [];
      }

      childData = childData.map(i => ({ ...i }));

      if (isJustLoadOrg) {
        return { errCode, errMsg, uerrCode: 0, uerrMsg: '', datas: childData }
      }
      const { datas: userData = [], errCode: uerrCode, errMsg: uerrMsg } = yield call(getUserByOrgCode, payload);
      const newUserData = userData.map(item => {
        const newItem = { ...item, isLeaf: true };
        // 确保是缺少extentAttributes的数据结构
        if (item.displayName && !item.extentAttributes && !item.extentAttribute) {
          newItem.extentAttributes = {
            ORG_CODE: orgCode,
            ORG_NAME: orgName,
          }
        }
        return newItem;
      });
      const resData = [...childData, ...newUserData];
      return { errCode, errMsg, uerrCode, uerrMsg, datas: resData }
    },
    *getUserListByNameFuzzy({ payload }, { call }) {
      const result = yield call(getUserListByNameFuzzy, payload);
      return result;
    },
    *selectEmployeeList({ payload }, { call, put, select }) {
      const { pageIndex } = payload;
      const { listSearchData } = yield select(_ => _.usertreeSelect);
      const result = yield call(selectEmployeeList, payload);
      const {
        datas: { dataList = [], total },
        errCode,
      } = result;
      if (errCode === 0) {
        if (listSearchData.length < total) {
          yield put({
            type: 'get/listSearchData',
            payload: pageIndex === 1 ? dataList : listSearchData.concat(dataList) || [],
          });
        } else if (listSearchData.length > total) {
          yield put({
            type: 'get/listSearchData',
            payload: dataList,
          });
        }
      }
      return result;
    },
  },
  reducers: {
    "set/cachedCodeOrgsMap": (state, { payload }) => ({
      ...state,
      cachedCodeOrgsMap: payload,
    }),
    "get/listSearchData": (state, { payload }) => ({
      ...state,
      listSearchData: payload,
    }),
    clearData: () => ({ ...initData }),
  },
};
